

package cn.shengchao.examstar.product.ohs.local.appservice;

import cn.hutool.core.util.ObjectUtil;
import cn.shengchao.base.enums.DisEnableStatusEnum;
import cn.shengchao.base.enums.ProductType;
import cn.shengchao.examstar.product.acl.ports.repositories.ICourseRepository;
import cn.shengchao.examstar.product.acl.ports.repositories.IProductRepository;
import cn.shengchao.examstar.product.domain.entity.*;
import cn.shengchao.examstar.product.domain.valobj.Price;
import cn.shengchao.examstar.product.infrastructure.dao.po.TProductCourse;
import cn.shengchao.examstar.product.ohs.local.message.KnowledgeNodeDto;
import cn.shengchao.examstar.product.ohs.local.message.ProductDto;
import cn.shengchao.examstar.product.ohs.local.message.ProductPayPriceDto;
import cn.shengchao.examstar.rpc.product.base.ContentProductTypeDefine;
import cn.shengchao.examstar.rpc.product.req.CourseNodeConfig;
import cn.shengchao.examstar.rpc.product.res.BatchUnlockConfig;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.stereotype.Service;
import top.continew.starter.cache.redisson.util.RedisUtils;
import top.continew.starter.core.exception.BusinessException;
import top.continew.starter.core.validation.ValidationUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Duration;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

import static cn.shengchao.base.constant.Constants.RedisKey.PRODUCT_KEY;

@Service
public class ProductAppService {

    @Autowired
    private IProductRepository iProductRepository;

    @Autowired
    private CourseService courseService;

    @Autowired
    private AsyncTaskExecutor asyncTaskExecutor;

    @Autowired
    private ICourseRepository iCourseRepository;
    //免费课程
    public FreeCourseKnowledgeProduct loadFreeProduct(Long nodeId){
        CourseKnowledgeNode courseNode = iCourseRepository.getCourseNode(nodeId);
        TProductCourse tProductCourse=iCourseRepository.ofCourse(courseNode.getCourseId());
        if (tProductCourse != null){
            return FreeCourseKnowledgeProduct.builder()
                .courseId(courseNode.getCourseId())
                .courseName(tProductCourse.getName())
                .discountPrice(courseNode.getDiscountPrice().getPrice())
                .productType(ObjectUtil.defaultIfNull(tProductCourse.getCourseType(),0)==1? ContentProductTypeDefine.COURSE_GK.name() : ContentProductTypeDefine.COURSE.name())
                .courseKnowledgeId(courseNode.getId())
                .courseKnowledgeName(courseNode.getName().getValue())
                .build();
        }
        return null;
    }

    // 获取产品名称
    public Map<Long, String> getProductName(List<Long> productIds) {
        return iProductRepository.findNameByIds(productIds);
    }

    public ProductDto getProductById(String productId) {
        ProductDto productDto = RedisUtils.get(PRODUCT_KEY + productId);
        if (productDto == null) {
            Optional<Product> productOptional = iProductRepository.findById(Long.valueOf(productId));
            Product product = productOptional.orElseThrow(() -> new BusinessException("产品不存在!"));
            ValidationUtils.throwIf(() -> !product.getStatus().equals(DisEnableStatusEnum.ENABLE), "产品下线");
            productDto = ProductDto.of(product);
            RedisUtils.set(PRODUCT_KEY + productId,productDto, Duration.ofDays(1));
        }
        return productDto;
    }

    public List<ProductManufacturer> getProductManufacturer(Long productId) {
        Optional<Product> productOptional = iProductRepository.findById(productId);
        if (productOptional.isPresent()) {
            Product product = productOptional.get();
            //如果是课程知识点
            if (product instanceof CourseKnowledgeNode courseKnowledgeNode) {
                ProductManufacturer productManufacturer = new ProductManufacturer();
                productManufacturer.setName(courseKnowledgeNode.getTeacher().getName());
                productManufacturer.setTeacherId(courseKnowledgeNode.getTeacher().getId());
                productManufacturer.setProductSum(1L);
                productManufacturer.setCreateTime(courseKnowledgeNode.getCreateTime());
                return Lists.newArrayList(productManufacturer);
            }
            //如果是课程
            if (product instanceof Course course) {
                //知识点的老师
                List<Teacher> teachers = iProductRepository.findTeacherByCourseId(productId);
                //每个老师的上课数量
                Map<Long, Long> teacherSum = teachers.stream()
                        .collect(Collectors.groupingBy(Teacher::getId, Collectors.counting()));
                List<ProductManufacturer> productManufacturers = new ArrayList<>();
                teachers.stream().distinct().forEach(teacher -> {
                    ProductManufacturer productManufacturer = new ProductManufacturer();
                    productManufacturer.setName(teacher.getName());
                    productManufacturer.setTeacherId(teacher.getId());
                    productManufacturer.setProductSum(teacherSum.get(teacher.getId()));
                    productManufacturer.setCreateTime(course.getCreateTime());
                    productManufacturers.add(productManufacturer);
                });
                return productManufacturers;
            }
        }
        return new ArrayList<>();
    }

    public ProductPayPriceDto calculateProductPayPrice(String productId, List<Long> subProductIds) {
        ProductPayPriceDto productPayPriceDto = new ProductPayPriceDto();
        //获取主要产品
        ProductDto product = getProductById(productId);
        productPayPriceDto.setProduct(product);
        if (product.getProductType().equals(ProductType.PRODUCT_MEMBER.name())) {
            productPayPriceDto.setPayPrice(product.getDiscountPrice());
            return productPayPriceDto;
        }
        if (product.getProductType().equals(ProductType.PRODUCT_THIRD_CAP.name())) {
            productPayPriceDto.setPayPrice(product.getDiscountPrice());
            return productPayPriceDto;
        }
        if (product.getProductType().equals(ProductType.PRODUCT_THIRD_YCBDC.name())) {
            productPayPriceDto.setPayPrice(product.getDiscountPrice());
            return productPayPriceDto;
        }
        List<ProductDto> subProducts = new ArrayList<>();
        if (!subProductIds.isEmpty()) {

            List<CompletableFuture<ProductDto>> completableFutures = new ArrayList<>();
            try (ExecutorService virtualThreadPool = Executors.newFixedThreadPool(subProductIds.size())) {
                for (Long subProductId : subProductIds) {

                        //获取子产品
                        CompletableFuture<ProductDto> productDtoCompletableFuture = CompletableFuture
                                .supplyAsync(() -> getProductById(subProductId.toString()), virtualThreadPool);
                        completableFutures.add(productDtoCompletableFuture);
                    }

                CompletableFuture.allOf(completableFutures.toArray(new CompletableFuture[0])).join();
                for (CompletableFuture<ProductDto> productDtoCompletableFuture : completableFutures) {
                    ProductDto productDto;
                    try {
                        productDto = productDtoCompletableFuture.get();
                    } catch (InterruptedException | ExecutionException e) {
                        throw new RuntimeException(e);
                    }
                    subProducts.add(productDto);
                }
                virtualThreadPool.close();
            }
        } else {
            subProductIds = new ArrayList<>();
        }
        productPayPriceDto.setSubProducts(subProducts);
        //获取批量解锁配置
        CourseNodeConfig config = courseService.getCourseNodeConfig(Long.valueOf(productId));
        //原价
        Optional<BigDecimal> price = subProducts.stream().map(ProductDto::getPrice).reduce(BigDecimal::add);
        if (config != null) {
            List<Long> finalSubProductIds = subProductIds;
            Optional<BatchUnlockConfig> batchUnlockConfig = config.getBatchUnlockConfig()
                    .stream()
                    //按购买数量最大值进行排序
                    .sorted(Comparator.comparingLong(BatchUnlockConfig::getCourseNodeSum).reversed())
                    //找到第一个满足条件的()
                    .filter(item -> item.getCourseNodeSum() <= finalSubProductIds.size())
                    .findFirst();

            batchUnlockConfig.ifPresent(item -> {
                //设置每一节的优惠价格
                for (ProductDto subProduct : subProducts) {
                    subProduct.setDiscountPrice(subProduct.getPrice()
                            .multiply(BigDecimal.valueOf(item.getDiscount()))
                            .divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP));
                }
                //保存优惠
                productPayPriceDto.setDiscountInfo(JSON.toJSONString(config));
            });
        }
        //支付金额(取课程折扣价)
        Optional<BigDecimal> payPrice = subProducts.stream().map(ProductDto::getDiscountPrice).reduce(BigDecimal::add);
        payPrice.ifPresent(productPayPriceDto::setPayPrice);
        payPrice.ifPresent(product::setDiscountPrice);
        price.ifPresent(product::setPrice);
        return productPayPriceDto;
    }

    public void updateCoursePrice(List<KnowledgeNodeDto> courseNodes, Long courseId) {
        Optional<Product> productOptional = iProductRepository.findById(courseId);
        if (productOptional.isPresent()) {
            Product product = productOptional.get();
            // 合并计算总价格和折扣价格
            BigDecimal sumPrice = BigDecimal.ZERO;
            BigDecimal discountPrice = BigDecimal.ZERO;
            for (KnowledgeNodeDto node : courseNodes) {
                sumPrice = sumPrice.add(BigDecimal.valueOf(node.getPrice()));
                discountPrice = discountPrice.add(BigDecimal.valueOf(node.getDiscountPrice()));
            }
            product.setPrice(Price.of(sumPrice));
            CourseNodeConfig config = courseService.getCourseNodeConfig(courseId);
            product.setDiscountPrice(Price.of(discountPrice));
            if (config != null) {
                List<BatchUnlockConfig> batchUnlockConfigs = config.getBatchUnlockConfig();
                if (batchUnlockConfigs != null) {
                    if (!batchUnlockConfigs.isEmpty()) {
                        batchUnlockConfigs.sort(Comparator.comparing(BatchUnlockConfig::getCourseNodeSum).reversed());
                        Optional<BatchUnlockConfig> batchUnlockConfig = config.getBatchUnlockConfig()
                                .stream()
                                //按购买数量最大值进行排序
                                .sorted(Comparator.comparingLong(BatchUnlockConfig::getCourseNodeSum).reversed())
                                //找到第一个满足条件的()
                                .filter(item -> item.getCourseNodeSum() <= courseNodes.size())
                                .findFirst();
                        if (batchUnlockConfig.isPresent()) {
                            BigDecimal discountRate = new BigDecimal(batchUnlockConfig.get().getDiscount());
                            BigDecimal discountedPrice = sumPrice.multiply(discountRate)
                                    .divide(BigDecimal.valueOf(100), RoundingMode.HALF_UP);
                            product.setDiscountPrice(Price.of(discountedPrice));
                        }
                    } else {
                        // 当配置存在但批量解锁配置为空时，使用原始折扣价总和
                        product.setDiscountPrice(Price.of(discountPrice));
                    }
                } else {
                    // 如果batchUnlockConfigs为null，也使用原始折扣价总和
                    product.setDiscountPrice(Price.of(discountPrice));
                }
            }
            if (product instanceof Course course) {
                course.setKnowledgeNodeNum(courseNodes.size());
                iCourseRepository.edit(course);
            }
        }
    }
}
